use std::fmt::{Display, Formatter, Error};

use std::result::Result;
/*链表节点*/
struct User{
    id: u32,
    name: String,
    next: Option<Box<User>>, //不能直接用Option<User>,User是本身，形成无限嵌套，编译器不知道该结构体的大小
}

impl User {
    fn new(id: u32, name: String) -> User{
        User{id, name, next: None}
    }
    //添加一下个节点
    fn add_next(&mut self, user: User){
        self.next = Some(Box::new(user));
    }

    fn remove_next(&mut self) -> Option<User> {
        let n = self.next.take();
        match n {
            Some(u) =>{Some(*u)},
            None =>None
        }
    }
}



///实现Drop
impl Drop for User{
    fn drop(&mut self){
        println!("drop user: id={},name={}", self.id, self.name);
    }
}
/// 实现Display
impl Display for User{
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
        println!("{}", format!("id = {}, name = {}", self.id, self.name));
        let mut next = &self.next;
        while next.is_some() {
            let id = &next.as_ref().unwrap().id;
            let name = &next.as_ref().unwrap().name; //借用，防止所有权转移
            println!("id = {}, name = {}", id, name);
            next = &(next.as_ref().unwrap().next);
        }
        Ok(())
    }
}

/*链表结构体*/
struct LinkedList{
    head: Option<Box<User>>,

    size: u32,
}

impl LinkedList {
    fn new() -> LinkedList {
        LinkedList {
            head:None,
            size:0
        }
    }
    ///添加节点 尾部
    fn add_next(&mut self, user: User) {
        if self.size == 0 {
            let b = Box::new(user);
            self.head = Some(b);
            
        }else {
            //获取Option包裹的实际对象的可变借用，返回一个新的Option
            let mut tmp = self.head.as_mut();
            for _ in 1..self.size {
                 tmp = tmp.unwrap().next.as_mut();
            }
            tmp.unwrap().add_next(user);
        }
        self.size += 1;
    }
    //添加节点 头部
    fn add_head(&mut self, user: User) {
        if self.size == 0 {
            self.head = Some(Box::new(user));
        }else {
            //取出head,head变为None
            let old_head = self.head.take();
            //重新设置head
            self.head = Some(Box::new(user));
            //新head的下一个指向old_head
            let u = old_head.unwrap();
            let u = *u;
            self.head.as_mut().unwrap().add_next(u);
        }
        self.size += 1;
    }
    //获取最后一个节点
    fn take_tail(&mut self) -> Option<User> {
        if self.size == 0 {
             None
        }else {
            
            let mut tmp = self.head.as_mut();
            for _ in 0..self.size - 2 {
                tmp = tmp.unwrap().next.as_mut();
            }
            self.size -=1;
            tmp.unwrap().remove_next()
        }
    }

    /// 获取头节点
    fn take_head(&mut self)->Option<User> {
        if self.size == 0 {
            None
        }else {
            //取出头节点
            let mut head = self.head.take();
            //解开
            let mut h_b = head.unwrap();
            //取出头节点的下一个
            let next = h_b.next.take();
            //头节点的下一个作为新的头节点
            self.head = next;
            //返回头节点
            Some(*h_b)
        }
        
        
    }


}

impl Display for LinkedList {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
        println!("list:\n{}", self.head.as_ref().unwrap());
        Ok(())
    }
}

pub fn demo(){
    let mut user = User::new(1,String::from("李四"));
    let mut user2 = User::new(2,String::from("王五"));
    let mut user3 = User::new(3,String::from("陈六"));
    user2.add_next(user3); //user3失效
    user.add_next(user2); // user2失效
    println!("{}", user);
}
/*链表演示*/
#[test]
pub fn link_list_demo(){
    let mut list = LinkedList::new();
    let  user = User::new(1,String::from("李四"));
    let  user2 = User::new(2,String::from("王五"));
    let  user3 = User::new(3,String::from("陈六"));
    let  user0 = User::new(0,String::from("张三"));
    list.add_next(user);
    list.add_next(user2);
    list.add_next(user3);
    list.add_next( User::new(3, String::from("老七")));
    list.add_head(user0);
    let tail = list.take_tail();
    match tail {
        Some(u) => {println!("tail:{}", u)},
        None=>{println!("tail:None")}
    }

    let head = list.take_head();
    match head {
        Some(u) => {println!("head:{}", u)},
        None=>{println!("head:None")}
    }


    println!("{}", list);
}